package com.stylefeng.guns.modular.netcar.service.impl;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.model.CommonKeyValue;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.AliMsgUtils;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.modular.netcar.dao.TaskInfMapper;
import com.stylefeng.guns.modular.netcar.model.*;
import com.stylefeng.guns.modular.netcar.service.*;
import com.stylefeng.guns.modular.system.service.ISysSerialnumInfService;
import com.stylefeng.guns.util.AppPush;
import com.taobao.api.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;


/**

 * 任务单信息 Service 实现 
 * @author sasazaixian
 * @Date 2018-10-25 18:14
 */
@Service
public class TaskInfServiceImpl extends ServiceImpl<TaskInfMapper,TaskInf> implements ITaskInfService {
    private static final String CACHE_STRATEGY = "local";
    @Resource
    private TaskInfMapper taskInfMapper;
    @Autowired
    private ISysSerialnumInfService sysSerialnumInfService;
    @Autowired
    private IOrderInfService orderInfService;
    @Autowired
    private ITaskOrderService taskOrderService;
    @Autowired
    private ITaskReleaseService taskReleaseService;
    @Autowired
    private IDriverInfService driverInfService;
    @Autowired
    private ILineDispatchPsnService lineDispatchPsnService;
    @Value("${spring.clientHotLine}")//#客户服务热线
    private String clientHotLine;

    /**
     * 删除任务单信息
     * @param taskInf
     * @return     
     */
    @Transactional
    public int deleteTaskInf(TaskInf taskInf,String token)throws Exception{
       /* if(taskInf==null ){
            throw new RuntimeException("参数不全！");
        }
        return this.taskInfMapper.deleteTaskInf(taskInf);*/
       return 0;
    }
    /**
     * 批量删除任务单信息
     * @param ids 主键ID数组
     * @return 
     */
    @Transactional
    public int deleteBatchTaskInf(String[] ids,String token)throws Exception{
        Date currentTime=DateTime.now();
        String suId = JwtTokenUtil.getClaimFromToken(token).getSubject();//用户ID
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        for(String id:ids){
            TaskInf taksInf=this.findTaskInfForUpdate(id);
            if(taksInf==null){
                throw  new RuntimeException("任务包不存在！");
            }
            if(!taksInf.getTiState().equals("0")){
                throw  new RuntimeException("订单已经指派或完成，不能操作！");
            }

            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(id);
            List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
            for(TaskOrder en:listTaskOrder){
                OrderInf orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
                if(orderInf.getCiState().equals("1") || orderInf.getCiState().equals("3") ){
                    throw  new RuntimeException("乘客已经上车或者下车，不能操作！");
                }
                //更新订单状态为未打包
                OrderInf updateOrderinf=new OrderInf();
                updateOrderinf.setOiPackageState("0");
                updateOrderinf.setOiId(orderInf.getOiId());
                updateOrderinf.setUpdateTime(currentTime);
                updateOrderinf.setUpdateUser(suId);
                orderInfService.updateOrderInf(updateOrderinf,token);
            }
            //删除任务订单关系
            taskOrderService.deleteTaskOrder(taskOrder,token);
            //删除抢单过程
            TaskRelease taskRelease=new TaskRelease();
            taskRelease.setTiId(id);
            taskReleaseService.deleteTaskRelease(taskRelease,token);
        }
        return this.taskInfMapper.deleteBatchTaskInf(ids);
    }
    /**
     * 查询任务单信息列表
     * @param taskInf 任务单信息对象
     * @return
     */
    public List<TaskInf> selectListTaskInf(TaskInf taskInf,String token)throws Exception{
        if(taskInf!=null && taskInf.getDispather()!=null && taskInf.getDispather().equals("1")){
            taskInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        return  this.taskInfMapper.selectListTaskInf(taskInf);
    }
    private String getDispatherLineIds(String token)throws Exception{
        LineDispatchPsn lineDispatchPsn=new LineDispatchPsn();
        String suId=JwtTokenUtil.getClaimFromToken(token).getSubject();
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        lineDispatchPsn.setSuId(suId);
        List<LineDispatchPsn> listDispatchPsn= lineDispatchPsnService.selectListLineDispatchPsn(lineDispatchPsn,token);
        String lineIds="";
        for(LineDispatchPsn en:listDispatchPsn){
            lineIds+=",'"+en.getOlId()+"'";
        }
        if(lineIds.length()>1){
            lineIds=lineIds.substring(1);
        }else{
            lineIds="''";
        }
        return lineIds;
    }
    /**
	 * 分页查询任务单信息列表
     * @param pager 分页对象
     * @return
     */     
    public  Map pageListTaskInf(Pager pager,String token) throws Exception{
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        TaskInf taskInf=(TaskInf)pager.getObj();
        if(taskInf!=null && taskInf.getDispather()!=null && taskInf.getDispather().equals("1")){
            taskInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        page.setRecords(taskInfMapper.selectListTaskInf(page,taskInf));
        List<TaskInf> list = page.getRecords();
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }
    /**
     * 车企查询需要指派或指派过得订单
     * @param pager 分页对象
     * @return
     */
    public  Map pageListDispatch(Pager pager,String token) throws Exception{
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        TaskInf taskInf=(TaskInf)pager.getObj();
        ShiroUser shiroUser=CacheKit.get(CACHE_STRATEGY,token);
        if(shiroUser==null || shiroUser.soId==null){
            throw new RuntimeException("请登录");
        }
        taskInf.setDiOrg(shiroUser.getSoId());
        page.setRecords(taskInfMapper.selectListTaskInf(page,taskInf));
        List<TaskInf> list = page.getRecords();
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }

    /**
     * 车企查询自己承运的订单
     * @param pager 分页对象
     * @return
     */
    public  Map pageListDriverOrg(Pager pager,String token) throws Exception{
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        TaskInf taskInf=(TaskInf)pager.getObj();
        ShiroUser shiroUser=CacheKit.get(CACHE_STRATEGY,token);
        if(shiroUser==null || shiroUser.soId==null){
            throw new RuntimeException("请登录");
        }
        taskInf.setDriverOrg(shiroUser.getSoId().toString());
        page.setRecords(taskInfMapper.selectListTaskInf(page,taskInf));
        List<TaskInf> list = page.getRecords();
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }
    /**
     * 同一个事务 互斥锁查询
     * @param taskInf 任务单信息对象
     * @return 
     */
    public  List<TaskInf> selectListTaskInfForUpdate(TaskInf taskInf)throws Exception{
        return  this.taskInfMapper.selectListTaskInfForUpdate(taskInf);
    }
    /**
     * 通过主键id查询的任务单信息列表
     * @param id 主键id
     * @return     
     */
    public  TaskInf findTaskInfById(String id,String token)throws Exception{
        return  this.taskInfMapper.findTaskInfById(id);
    }

    /**
     * 查询锁 获取对象信息
     * @param id 主键id
     * @return
     * @throws Exception
     */
    @Override
    public TaskInf findTaskInfForUpdate(String id) throws Exception {
        return  this.taskInfMapper.findTaskInfForUpdate(id);
    }

    /**
     * 新增任务单信息数据
     * @param taskInf  任务单信息对象
     * @param token  登录令牌
     * @param checkOrder  是否验证订单（只有订单和任务一起保存时不用验证）
     */
    @Transactional
    public int insertTaskInf(TaskInf taskInf,String token,boolean checkOrder) throws Exception {
        if(taskInf!=null && (taskInf.getTiId()==null || taskInf.getTiId().trim().length()<10)){
            taskInf.setTiId(IdWorker.get32UUID());
        }
        String[] orderIds=taskInf.getOrderIdArry().split(",");
        String dateFormatStr=new SimpleDateFormat("yyyyMMdd").format(taskInf.getCreateTime());
        String taskId=taskInf.getTiId();
        double  maxKm=0;
        OrderInf maxkmOrder=null;
        int cntCustomer=0;
        String driverTel="";
        DriverInf driverInf=null;
        Date minDate=new Date();
        if(taskInf.getDiId()!=null && taskInf.getDiId().trim().length()>10){
            driverInf=getDriverPhone(taskInf.getDiId(),token);
            driverTel=driverInf.getDiPhone();
        }
        //去订单最大里程的作为任务包的类型
        String OrderType="";
        for(String orderid:orderIds){

            OrderInf orderinf=orderInfService.findOrderInfForUpdate(orderid);
            if(orderinf==null ){
                throw new RuntimeException("订单不存在！");
            }
            if(checkOrder){
                if(orderinf.getOiPackageState().equals("1")){
                    throw new RuntimeException("乘客【"+orderinf.getCiName()+"】的订单已经打包 ，请重新选择订单进行打包！");
                }
                if(!orderinf.getCiState().equals("0")){
                    throw new RuntimeException("乘客【"+orderinf.getCiName()+"】的订单不是未乘车状态！");
                }
                //打包是专车和快车不能同时打包！
                if(OrderType.equals("")){
                    OrderType=orderinf.getOstId();
                }else{
                    if(!OrderType.equals(orderinf.getOstId())){
                        throw new RuntimeException("专车不能快车同时创建任务单！");
                    }
                }

            }
            if(!orderinf.getPayState().equals("1")){
                throw new RuntimeException("乘客【"+orderinf.getCiName()+"】的订单未支付！");
            }
            cntCustomer=cntCustomer+orderinf.getCiNum();
            if(orderinf.getOiDistance()>maxKm ){
                maxKm=orderinf.getOiDistance();
                maxkmOrder=orderinf;
            }
            if(minDate.compareTo(orderinf.getCiSendTime())>0 ){
                minDate=orderinf.getCiSendTime();
            }
            //更新订单状态为已经打包
            OrderInf updateOrderinf=new OrderInf();
            updateOrderinf.setOiPackageState("1");
            updateOrderinf.setOiId(orderid);
            updateOrderinf.setUpdateTime(taskInf.getCreateTime());
            updateOrderinf.setUpdateUser(taskInf.getCreateUser());
            orderInfService.updateOrderInf(updateOrderinf,token);

            //插入任务订单关系
            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(taskId);
            taskOrder.setOiId(orderinf.getOiId());
            taskOrderService.insertTaskOrder(taskOrder,token);
            //发送已经调度短信
            if(taskInf.getDiId()!=null && taskInf.getDiId().trim().length()>10){
                this.sendSmsToCustomer(taskInf.getDiName(),orderinf.getCiTel(),taskInf.getDiVehiclePlate(),driverTel,orderinf.getOiQrcode(),orderinf.getCiSendTime());
            }
        }
        if(maxkmOrder==null){
            throw new RuntimeException("订单信息中里程信息为空，不能打包！");
        }
        //设置订单距离最远的订单类型作为任务类型
        taskInf.setOtId(maxkmOrder.getOtId());
        taskInf.setOtName(maxkmOrder.getOtName());
        //任务总人数
        taskInf.setTiCustomerCount(cntCustomer);
        taskInf.setTiCode(sysSerialnumInfService.updateSysSerialnumInf(maxkmOrder.getOtId()+"O",dateFormatStr,6,token));
        taskInf.setOlName(maxkmOrder.getOlName());
        taskInf.setOlId(maxkmOrder.getOlId());
        taskInf.setFirstSendTime(minDate);
        if(taskInf.getTiIsPublish()==null){
            taskInf.setTiIsPublish("1");//已发布
        }
        if(taskInf.getTiDispatchType()==null){
            taskInf.setTiDispatchType("1");//派单
        }
        if(taskInf.getTiCheckResult()==null){
            taskInf.setTiCheckResult("1");//0：未审核1：审核
        }

        //登记派单过程
        if(taskInf.getDiId()!=null && taskInf.getDiId().trim().length()>10){
            taskInf.setTiTaskGetTime(taskInf.getCreateTime());//派单时间
            taskInf.setTiState("1");//0未接单，1已接单，2已完结
            this.taskInfMapper.insertTaskInf(taskInf);
            TaskRelease taskRelease=new TaskRelease();
            taskRelease.setTiId(taskId);
            taskRelease.setDiId(taskInf.getDiId());
            taskRelease.setTrTakeTime(taskInf.getCreateTime());
            taskReleaseService.insertTaskRelease(taskRelease,token);
            //更细驾驶员任务数
            driverInfService.updateDriverInfTaskNum(taskInf.getDiId(),1);

            this.sendSmsToDriver(taskInf.getDiName(),driverTel,maxkmOrder.getOlName(),minDate);
            this.pushMsgToDriver(1,null,driverInf.getDiClientId());
        }else{
            taskInf.setTiState("0");
            this.taskInfMapper.insertTaskInf(taskInf);
        }

        return 0;
    }
    @Override
    @Transactional
    public int insertOrderAndTaskInf(TaskInf taskInf, String token) throws Exception {
        String dateFormatStr=new SimpleDateFormat("yyyyMMdd").format(taskInf.getCreateTime());
        if(taskInf==null ||
                taskInf.getDiId()==null || taskInf.getDiId().trim().length()<10 ||
                taskInf.getDiVehiclePlate()==null || taskInf.getDiVehiclePlate().trim().length()<5 ||
                taskInf.getOrderArry()==null || taskInf.getOrderArry().length()<10
                ){
                 throw  new RuntimeException("参数不全！");
        }
        String orderIds="";
        JSONArray arryOBj=JSONArray.parseArray(taskInf.getOrderArry());
        List<Map> customerList=new ArrayList();
        for(int i=0;i<arryOBj.size();i++) {
            OrderInf orderInf=arryOBj.getObject(i,OrderInf.class);
            String orderId=IdWorker.get32UUID();
            orderInf.setOiId(orderId);
            orderInf.setOiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId()+"O",dateFormatStr,6,token));
            orderInf.setPayState("1");//已支付
            orderInf.setCiState("1");//已乘车
            orderInf.setOiPackageState("0");//未打包
            orderInf.setCiGetOnTime(taskInf.getCreateTime());
            orderInf.setCiGetOnPos(orderInf.getOiStartPoint());
            orderInf.setCiGetOnAddr(orderInf.getOiStartAddress());
            orderInf.setCreateUser(taskInf.getCreateUser());
            orderInf.setCreateTime(taskInf.getCreateTime());
            orderInfService.insertOrderInf(orderInf,token,false);

            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String orderTime=sdf.format(orderInf.getCiSendTime());
            if(orderInf.getOiOrderTimeStart()!=null && orderInf.getOiOrderTimeEnd()!=null){
                orderTime=sdf.format(orderInf.getOiOrderTimeStart())+"-"+sdf.format(orderInf.getOiOrderTimeEnd());
            }
            Map<String,String> hmPrms =new HashMap<String,String>();
            hmPrms.put("from", orderInf.getOiStartAddress());
            hmPrms.put("to",  orderInf.getOiEndAddress());
            hmPrms.put("time",orderTime);
            hmPrms.put("tel", clientHotLine);
            hmPrms.put("revcTel",orderInf.getCiTel());
            customerList.add(hmPrms);

            orderIds+=","+orderId;
            if(i==0){
                taskInf.setTiStartPoint(orderInf.getOiStartPoint());
                taskInf.setCtStartAddress(orderInf.getOiStartAddress());
                taskInf.setTiStartTime(taskInf.getCreateTime());
            }
        }
        if(orderIds.length()>0){
            orderIds=orderIds.substring(1);
        }
        taskInf.setOrderIdArry(orderIds);
        taskInf.setTiTaskGetTime(taskInf.getCreateTime());//派单时间

        taskInf.setTiState("1");//0未接单，1已接单，2已完结
        taskInf.setNote("下单组包指派一体化操作！");
        taskInf.setTiIsPublish("1");//已发布
        taskInf.setTiDispatchType("1");//0:抢;1:派;2:自创并且抢
        insertTaskInf(taskInf,token,false);
        for(Map<String,String> map:customerList){
            String tel=map.get("revcTel");
            map.remove("revcTel");
            AliMsgUtils.sendSmsNotice(tel,"SMS_144853288",map);
        }
        return 0;
    }

    /**
     * 更新任务单信息数据
     * @param taskInf 任务单信息对象
     * @return     
     */
    @Transactional
    public int updateTaskInf(TaskInf taskInf,String token) throws Exception {
        String tiId=taskInf.getTiId();
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null){
            throw  new RuntimeException("任务包不存在！");
        }
        Date curDate=new Date();
        if(taskInf.getDiId()!=null && taskInf.getDiId().trim().length()>0 && taskInf.getDiVehicleNo()!=null && taskInf.getDiVehicleNo().trim().length()>0
            &&(taksInf.getDiId()==null || taksInf.getDiVehicleNo()==null
                || !taksInf.getDiId().equals(taskInf.getDiId()) || taksInf.getDiVehicleNo().equals(taskInf.getDiVehicleNo()))){

            //重新指派驾驶员或车辆
            if(!taksInf.getTiState().equals("0")){
                throw  new RuntimeException("订单已经指派或完成，不能操作！");
            }
            if(taksInf.getDiId()!=null && taksInf.getDiId().length()>10){
                //减少原驾驶员任务数
                driverInfService.updateDriverInfTaskNum(taksInf.getDiId(),-1);
                this.pushMsgToDriver(-1,taksInf.getDiId(),null);
            }
            DriverInf driverInf=getDriverPhone(taskInf.getDiId(),token);
            String driverTel=driverInf.getDiPhone();
            double maxKm=0;
            OrderInf maxkmOrder=null;
            //重新指派驾驶员 后发送短信
            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(tiId);
            Date minDate=new Date();
            List<TaskOrder> taskOrderList= taskOrderService.selectListTaskOrder(taskOrder,token);
            for(TaskOrder sub:taskOrderList){
                OrderInf orderInf=orderInfService.findOrderInfById(sub.getOiId(),token);
                if(!orderInf.getCiState().equals("0")){
                    throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单不是未乘车状态！");
                }
                if(!orderInf.getPayState().equals("1")){
                    throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单未支付！");
                }
                if(orderInf.getOiDistance()>maxKm){
                    maxKm=orderInf.getOiDistance();
                    maxkmOrder=orderInf;
                }
                if(minDate.compareTo(orderInf.getCiSendTime())>0){
                    minDate=orderInf.getCiSendTime();
                }
                this.sendSmsToCustomer(taskInf.getDiName(),orderInf.getCiTel(),taskInf.getDiVehiclePlate(),driverTel,orderInf.getOiQrcode(),orderInf.getCiSendTime());
            }
            //更新曾经派单的过程
            TaskRelease taskRelease=new TaskRelease();
            taskRelease.setTiId(tiId);
            taskReleaseService.updateTaskReleaseBatch(taskRelease,token);
            //添加抢单过程
            taskRelease=new TaskRelease();
            taskRelease.setTiId(tiId);
            taskRelease.setDiId(taskInf.getDiId());
            taskRelease.setTrTakeTime(curDate);
            taskReleaseService.insertTaskRelease(taskRelease,token);
            //设置订单派单必要数据
            taskInf.setTiTaskGetTime(curDate);//派单时间
            taskInf.setTiState("1");//0未接单，1已接单，2已完结
            taskInf.setTiIsPublish("1");//已发布
            taskInf.setTiDispatchType("1");//0:抢;1:派;2:自创并且抢
            //增加新指派驾驶员任务数
            driverInfService.updateDriverInfTaskNum(taskInf.getDiId(),1);

            this.sendSmsToDriver(taskInf.getDiName(),driverTel,maxkmOrder.getOlName(),maxkmOrder.getCiSendTime());
            this.pushMsgToDriver(1,null,driverInf.getDiClientId());

            taskInf.setOlName(maxkmOrder.getOlName());
            taskInf.setOlId(maxkmOrder.getOlId());
            taskInf.setFirstSendTime(minDate);
        }
        return  this.taskInfMapper.updateTaskInf(taskInf);
    }
    /**
     * 更新任务-（新增订单/移动订单）
     * @param tiId 任务ID
     * @param oiId 订单ID
     * @param ope 操作：I(insert)/D(del)
     * @return
     */
    @Transactional
    public int updateTaskInfOpeOrder(String tiId,String oiId,String ope,String token) throws Exception {
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null){
            throw  new RuntimeException("任务包不存在！");
        }
        OrderInf orderInf=orderInfService.findOrderInfForUpdate(oiId);
        if(orderInf==null ){
            throw  new RuntimeException("订单不存在！");
        }
        if(orderInf.getCiState().equals("1") ||orderInf.getCiState().equals("3") ){
            throw  new RuntimeException("乘客已近乘车，不能操作！");
        }

        Date currentTime=DateTime.now();
        String suId = JwtTokenUtil.getClaimFromToken(token).getSubject();//用户ID
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        if(ope.equals("I")){//任务包插入订单
            if(!orderInf.getOiPackageState().equals("0")){
               throw  new RuntimeException("此订单已经打包！");
            }
            if(!orderInf.getCiState().equals("0")){
                throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单不是未乘车状态！");
            }
            if(!orderInf.getPayState().equals("1")){
                throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单未支付！");
            }
            //更新订单状态为已经打包
            OrderInf updateOrderinf=new OrderInf();
            updateOrderinf.setOiPackageState("1");
            updateOrderinf.setOiId(oiId);
            updateOrderinf.setUpdateTime(currentTime);
            updateOrderinf.setUpdateUser(suId);
            orderInfService.updateOrderInf(updateOrderinf,token);

            //插入任务订单关系
            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(tiId);
            taskOrder.setOiId(oiId);
            taskOrderService.insertTaskOrder(taskOrder,token);
            //发送已经调度短信
            if(taksInf.getDiId()!=null && taksInf.getDiId().trim().length()>10){
                this.sendSmsToCustomer(taksInf.getDiName(),orderInf.getCiTel(),taksInf.getDiVehiclePlate(),getDriverPhone(taksInf.getDiId(),token).getDiPhone(),orderInf.getOiQrcode(),orderInf.getCiSendTime());
            }
        }else if(ope.equals("D")){//任务包删除订单
            //移动任务订单关系
            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(tiId);
            taskOrder.setOiId(oiId);
            taskOrderService.deleteTaskOrder(taskOrder,token);
            //更新订单状态为未打包
            OrderInf updateOrderinf=new OrderInf();
            updateOrderinf.setOiPackageState("0");
            updateOrderinf.setOiId(oiId);
            updateOrderinf.setUpdateTime(currentTime);
            updateOrderinf.setUpdateUser(suId);
            orderInfService.updateOrderInf(updateOrderinf,token);
        }else{
            return 0;
        }
        taksInf.setTiCustomerCount(orderInf.getCiNum());

        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        Date minDate=new Date();
        double maxKm=0;
        OrderInf maxkmOrder=null;
        List<TaskOrder> taskOrderList= taskOrderService.selectListTaskOrder(taskOrder,token);
        String orderType="";
        for(TaskOrder sub:taskOrderList){
            orderInf=orderInfService.findOrderInfById(sub.getOiId(),token);
            if(orderType.equals("")){
                orderType=orderInf.getOstId();
            }else{
                if(!orderType.equals(orderInf.getOstId())){
                    throw new RuntimeException("专车不能快车同时创建任务单！");
                }

            }
            if(!orderInf.getCiState().equals("0")){
                throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单不是未乘车状态！");
            }
            if(!orderInf.getPayState().equals("1")){
                throw new RuntimeException("乘客【"+orderInf.getCiName()+"】的订单未支付！");
            }
            if(orderInf.getOiDistance()>maxKm){
                maxKm=orderInf.getOiDistance();
                maxkmOrder=orderInf;
            }
            if(minDate.compareTo(orderInf.getCiSendTime())>0){
                minDate=orderInf.getCiSendTime();
            }
        }
        taksInf.setOpe(ope);
        taksInf.setUpdateUser(suId);
        taksInf.setUpdateTime(currentTime);
        taksInf.setOlName(maxkmOrder.getOlName());
        taksInf.setOlId(maxkmOrder.getOlId());
        taksInf.setFirstSendTime(minDate);
        this.taskInfMapper.updateTaskCustomerNum(taksInf);
        return 0;
    }

    /***
     * 取消指派任务
     * @param tiId 任务ID
     * @param token 操作：I(insert)/D(del)
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateTaskInfCancelDispatch(String tiId, String token) throws Exception {
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("3") ){
            throw  new RuntimeException("任务包未指派或已经完成，不能操作！");
        }

        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
            if(orderInf.getCiState().equals("1") || orderInf.getCiState().equals("3") ){
                throw  new RuntimeException("乘客已经上车或者下车，不能操作！");
            }
        }
        if(taksInf.getDiId()!=null){
            //减少原驾驶员任务数
            driverInfService.updateDriverInfTaskNum(taksInf.getDiId(),-1);
            this.pushMsgToDriver(-1,taksInf.getDiId(),null);
        }

        //更新曾经派单的过程
        TaskRelease taskRelease=new TaskRelease();
        taskRelease.setTiId(tiId);
        taskReleaseService.updateTaskReleaseBatch(taskRelease,token);

        Date currentTime=DateTime.now();
        String suId = JwtTokenUtil.getClaimFromToken(token).getSubject();//用户ID
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        taksInf.setUpdateTime(currentTime);
        taksInf.setUpdateUser(suId);
        this.taskInfMapper.updateTaskCancelDispatch(taksInf);
        return 0;
    }

    /**
     * 查询任务单信息返回key-Value属性
     * @param taskInf 系统操作对象
     * @return     
     */
    public List<CommonKeyValue> optionsTaskInf(TaskInf taskInf,String token) throws Exception {
        List<TaskInf> listTaskInf=this.taskInfMapper.selectListTaskInf(taskInf);
        List<CommonKeyValue> listOptions=new ArrayList<CommonKeyValue>();
        for(TaskInf item:listTaskInf){
            CommonKeyValue opts=new CommonKeyValue();
            opts.setId(""+item.getTiId());
            opts.setValue(item.getTiId());
            listOptions.add(opts);
        }
        return listOptions;
    }
    /**
     * 根据驾驶员ID获取驾驶员手机号
     * @param driverId 驾驶员ID
     * @return 驾驶员手机
     * @throws Exception
     */
    private DriverInf getDriverPhone(String driverId,String token) throws Exception{
        DriverInf driverInf=driverInfService.findDriverInfById(driverId,token);
        return driverInf;
    }

    /**
     * 发送派单通知短信
     * @param drivieName 驾驶员姓名
     * @param mobile 手机号
     * @param carNo 车牌号
     * @param driverTel 驾驶员手机
     * @param qrcode 乘车码
     * @return
     */
    private void sendSmsToCustomer(String drivieName,String mobile,String carNo,String driverTel,String qrcode,Date sendTime){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Map<String,String> hm =new HashMap<String,String>();
        hm.put("driver", drivieName);
        hm.put("drivertel", driverTel);
        hm.put("carid", carNo);
        hm.put("time", sdf.format(sendTime));
        hm.put("tel", clientHotLine);
        try {
            AliMsgUtils.sendSmsNotice(mobile,"SMS_144853289",hm);
        } catch (ApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     *  模版CODE:
     *  SMS_150860517
     *  模版内容:
     *  驾驶员${driver}您已收到城际派单，线路${route}，时间${time}，请打开城际司机端app处理。
     * @param drivieName 驾驶员姓名
     * @param mobile 手机号
     * @param routeName 线路名称
     * @param sendTime 预约时间
     * @return
     */
    private void sendSmsToDriver(String drivieName,String mobile,String routeName,Date sendTime){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Map<String,String> hm =new HashMap<String,String>();
        hm.put("driver", drivieName);
        hm.put("route", routeName);
        hm.put("time", sdf.format(sendTime));
        try {
            AliMsgUtils.sendSmsNotice(mobile,"SMS_150860517",hm);
        } catch (ApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 给驾驶员App推送消息
     * @param ope 1 派单 0 取消派单
     * @param diId 驾驶员Id
     * @param cId 驾驶员登录使用设备ID  和驾驶员Id参数二选一
     * @throws Exception
     */
    private void pushMsgToDriver(int  ope,String diId,String cId)throws Exception{
        if((cId==null || cId.trim().length()<5) &&( diId==null ||  diId.trim().length()<5)){
            return ;
        }
        String content="";
        if(cId==null || cId.trim().length()<5){
            DriverInf driverInf=this.getDriverPhone(diId,null);
            cId=driverInf.getDiClientId();
        }
        if(cId==null || cId.trim().length()<5){
            return ;
        }
        if(ope==1){
            content="{\"ope\":\"add\"}";
        }else{
            content="{\"ope\":\"cancel\"}";
        }
        AppPush.sendmsg(content,cId);
    }

    /**
     * 上车
     * @param tiId
     * @param diId
     * @param token
     * @param onAddr
     * @param onPos
     * @throws Exception
     */
    private void scanCodeUp(String tiId,String qrcode,String diId,String token,String  onAddr,String onPos )throws Exception{

        if(onAddr==null || onAddr.trim().length()<3 || onPos==null || onPos.trim().length()<10){
            throw  new RuntimeException("上车经纬度和地址都不能为空！");
        }
        //检查任务包状态
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        if(!taksInf.getDiId().equals(diId)){
            throw  new RuntimeException("任务包已经指派他人！");
        }
        OrderInf orderInf=orderInfService.findOrderInfByQrcodeForUpdate(qrcode);
        if(orderInf==null ){
            throw  new RuntimeException("订单不存在！");
        }
        if(orderInf.getCiState().equals("0")){
            throw  new RuntimeException("乘客不是未上车状态，不能操作！");
        }
        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        taskOrder.setOiId(orderInf.getOiId());
        List list=taskOrderService.selectListTaskOrder(taskOrder,token);
        if(list==null || list.size()==0){
            throw  new RuntimeException("此任务单不在本次任务中！");
        }
        Date curDate=new Date();
        orderInf.setCiGetOnTime(curDate);
        orderInf.setCiGetOnPos(onPos);
        orderInf.setCiGetOnAddr(onAddr);
        orderInfService.updateOrderInfUp(orderInf,token);

        //如果第一个乘客扫码上车  记录任务开始执行时间、坐标和地址
        if(taksInf.getTiStartTime()==null){
            TaskInf updateTaksInf=new TaskInf();
            updateTaksInf.setTiId(tiId);
            updateTaksInf.setUpdateTime(curDate);
            updateTaksInf.setTiStartTime(curDate);
            updateTaksInf.setTiStartPoint(onPos);
            updateTaksInf.setCtStartAddress(onAddr);
            this.taskInfMapper.updateTaskInf(updateTaksInf);
        }
    }

    /**
     * 下车
     * @param tiId
     * @param oiId
     * @param token
     * @param offAddr
     * @param offPos
     * @throws Exception
     */
    private void scanCodeDown(String tiId,String oiId,String token,String  offAddr,String offPos)throws Exception{
        //检查任务包状态
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        OrderInf orderInf=orderInfService.findOrderInfForUpdate(oiId);
        if(orderInf==null ){
            throw  new RuntimeException("订单不存在！");
        }
        if(orderInf.getCiState().equals("1")){
            throw  new RuntimeException("乘客未上车不能操作！");
        }
        Date curDate=new Date();
        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        taskOrder.setOiId(oiId);
        List list=taskOrderService.selectListTaskOrder(taskOrder,token);
        if(list==null || list.size()==0){
            throw  new RuntimeException("此任务单不在本次任务中！");
        }
        //更新订单状态为已下车 记录下车时间、坐标和地址
        orderInf.setCiGetOffTime(curDate);
        orderInf.setCiGetOffPos(offPos);
        orderInf.setCiGetOffAddr(offAddr);
        orderInfService.updateOrderInfDown(orderInf,token);


        //查询所有乘客已经下车  将任务包修改成已经完成  并且记录完成经纬度和时间
        taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        for(TaskOrder en:listTaskOrder){
            orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
            if(!orderInf.getCiState().equals("3")  ){
                return ;
            }
        }
        TaskInf updateTaksInf=new TaskInf();
        updateTaksInf.setTiId(tiId);
        updateTaksInf.setUpdateTime(curDate);
        updateTaksInf.setTiEndTime(curDate);
        updateTaksInf.setTiEndPoint(offPos);
        updateTaksInf.setCtEndAddress(offAddr);
        updateTaksInf.setTiState("2");
        this.taskInfMapper.updateTaskInf(updateTaksInf);
        //减少原驾驶员任务数
        driverInfService.updateDriverInfTaskNum(taksInf.getDiId(),-1);
    }

    /**
     * 结束任务 将订单的状态修改成已下车 任务状态修改成已完成
     * @param tiId
     * @param token
     * @param offAddr
     * @param offPos
     * @throws Exception
     */
    private void  updateEndTask(String tiId,String token,String  offAddr,String offPos)throws Exception{
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        Date curDate=new Date();

        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        //将任务中的订单修改称已经下车 并且记录下车位置和坐标
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
            if(!orderInf.getCiState().equals("3") && !orderInf.getCiState().equals("2") ){
                orderInf.setCiGetOffTime(curDate);
                orderInf.setCiGetOffPos(offPos);
                orderInf.setCiGetOffAddr(offAddr);
                orderInfService.updateOrderInfDown(orderInf,token);
            }
        }
        //更新任务状态为已完成 记录时间、经纬度和地址。
        TaskInf updateTaksInf=new TaskInf();
        updateTaksInf.setTiId(tiId);
        updateTaksInf.setUpdateTime(curDate);
        updateTaksInf.setTiEndTime(curDate);
        updateTaksInf.setTiEndPoint(offPos);
        updateTaksInf.setCtEndAddress(offAddr);
        updateTaksInf.setTiState("2");
        this.taskInfMapper.updateTaskInf(updateTaksInf);
        //减少原驾驶员任务数
        driverInfService.updateDriverInfTaskNum(taksInf.getDiId(),-1);
    }

    /***
     * 开始执行任务
     * @param tiId
     * @param diId
     * @param token
     * @param offAddr
     * @param offPos
     * @throws Exception
     */
    private void  updateStartTask(String tiId,String diId,String token,String  offAddr,String offPos)throws Exception{
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        if(!taksInf.getDiId().equals(diId)){
            throw  new RuntimeException("任务包已经指派他人！");
        }
        Date curDate=new Date();
        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        //将任务中的订单修改称已经上车 并且记录上车位置和坐标
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
            if(!orderInf.getCiState().equals("1") &&  !orderInf.getCiState().equals("2")  ){
                orderInf.setCiGetOffTime(curDate);
                orderInf.setCiGetOffPos(offPos);
                orderInf.setCiGetOffAddr(offAddr);
                orderInfService.updateOrderInfUp(orderInf,token);
            }
        }
        //更新任务执行时间 执行点坐标 地址
        TaskInf updateTaksInf=new TaskInf();
        updateTaksInf.setTiId(tiId);
        updateTaksInf.setUpdateTime(curDate);
        updateTaksInf.setTiStartTime(curDate);
        updateTaksInf.setTiStartPoint(offPos);
        updateTaksInf.setCtStartAddress(offAddr);
        this.taskInfMapper.updateTaskInf(updateTaksInf);
    }
    /**
     * 自动打包
     */
    @Transactional
    public void autoPackegeTask() throws Exception{
        List<TaskInf> listOrderInf=this.taskInfMapper.selectAutoPackageTask();
        Date curDate=new Date();
        String dateFormatStr=new SimpleDateFormat("yyyyMMdd").format(curDate);

        for(TaskInf taskInf:listOrderInf){
            String orderId=taskInf.getOiId();
            OrderInf orderInf=orderInfService.findOrderInfForUpdate(orderId);
            if(!(orderInf.getPayState().equals("1") && orderInf.getCiState().equals("0") && orderInf.getOiPackageState().equals("0") && orderInf.getOiAutoPackaged().equals("0")
                    && orderInf.getOstId().equals("0"))){//未打包 //已支付 //未乘车 从未打包过 专车
                continue;
            }
            String taskId=IdWorker.get32UUID();
            //更新订单状态为已经打包
            OrderInf updateOrderinf=new OrderInf();
            updateOrderinf.setOiPackageState("1");//已打包
            updateOrderinf.setOiId(orderId);
            updateOrderinf.setUpdateTime(curDate);
            updateOrderinf.setOiAutoPackaged("1");//已经自动打包过
            orderInfService.updateOrderInf(updateOrderinf,"");
            //插入任务订单关系
            TaskOrder taskOrder=new TaskOrder();
            taskOrder.setTiId(taskId);
            taskOrder.setOiId(orderId);
            taskOrderService.insertTaskOrder(taskOrder,"");
            //插入任务
            TaskInf inserTaskInf=new TaskInf();
            inserTaskInf.setTiId(taskId);
            inserTaskInf.setOtId(orderInf.getOtId());
            inserTaskInf.setOtName(orderInf.getOtName());
            inserTaskInf.setOlId(orderInf.getOlId());
            inserTaskInf.setOlName(orderInf.getOlName());
            //任务总人数
            inserTaskInf.setTiCustomerCount(orderInf.getCiNum());
            inserTaskInf.setTiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId()+"O",dateFormatStr,6,""));
            inserTaskInf.setTiIsPublish("1");//已发布
            inserTaskInf.setCreateTime(curDate);
            inserTaskInf.setTiState("0");
            inserTaskInf.setNote("自动打包");
            inserTaskInf.setFirstSendTime(orderInf.getCiSendTime());
            inserTaskInf.setTiCheckResult("1");
            inserTaskInf.setTiIsPublish("1");
            inserTaskInf.setTiDispatchType("1");
            this.taskInfMapper.insertTaskInf(inserTaskInf);
        }
    }
}
